//////////////////////////////////////////////////////////////////////////
// $Id: MReference.cpp,v 1.1 2009/04/03 12:46:10 sunjun Exp $
//////////////////////////////////////////////////////////////////////////

#include "Local.h"

//////////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////////

NAMESPACE_BEGIN

//////////////////////////////////////////////////////////////////////////

	MReference::MReference() :
		mRefMutex(NULL),
		mRefCount(0)
	{
		GUARD(MReference::MReference);

		UNGUARD;
	}

	MReference::~MReference()
	{
		GUARD(MReference::~MReference);

		if( mRefMutex )
		{
			MMutex* tmp_mutex_ptr = mRefMutex;
			mRefMutex = 0;
			MDELETE(tmp_mutex_ptr);
		}
	
		UNGUARD;
	}

	/*
	====================
	ref
	====================
	*/
	INLINE VOID MReference::ref() const
	{
		GUARD(MReference::ref);

		if( mRefMutex )
		{
			MLock lock(mRefMutex);
			++mRefCount;
		}
		else
		{
			++mRefCount;
		}

		UNGUARD;
	}

	/*
	====================
	unref
	====================
	*/
	INLINE VOID MReference::unref() const
	{
		GUARD(MReference::unref);

		BOOL is_delete = FALSE;
		if(mRefMutex)
		{
			MLock lock(mRefMutex);
			--mRefCount;
			is_delete = mRefCount<=0 ? TRUE : FALSE;
		}
		else
		{
			--mRefCount;
			is_delete = mRefCount<=0 ? TRUE : FALSE;
		}

		if(is_delete)MDELETE(this);

		UNGUARD;
	}

	/*
	====================
	count
	====================
	*/
	INLINE I32 MReference::count() const
	{
		GUARD(MReference::count);

		I32 refCount = 0;
		if( mRefMutex )
		{
			MLock lock(mRefMutex);
			refCount = mRefCount;
		}
		else
		{
			refCount = mRefCount;
		}
		return refCount;

		UNGUARD;
	}

	/*
	====================
	safe
	====================
	*/
	INLINE VOID MReference::safe( BOOL is_safe )
	{
		GUARD(MReference::safe);

		if( is_safe )
		{
			if( !mRefMutex )
			{
				mRefMutex = MNEW(MMutex); CHECK( mRefMutex );
			}
		}
		else
		{
			if( mRefMutex )
			{
				MMutex* tmp_mutex_ptr = mRefMutex;
				mRefMutex = 0;
				MDELETE(tmp_mutex_ptr);
			}
		}	

		UNGUARD;
	}

	/*
	====================
	mutex
	====================
	*/	
	INLINE MMutex* MReference::mutex() const
	{
		GUARD(MReference::mutex);

		return mRefMutex;

		UNGUARD;
	}
	
//////////////////////////////////////////////////////////////////////////
	
NAMESPACE_END
		
//////////////////////////////////////////////////////////////////////////
